/*******************************************************************************
* Copyright (c) 2010, 2018 西安秦晔信息科技有限公司
* Licensed under the Apache License, Version 2.0 (the "License");
*    you may not use this file except in compliance with the License.
*    You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*    Unless required by applicable law or agreed to in writing, software
*    distributed under the License is distributed on an "AS IS" BASIS,
*    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*    See the License for the specific language governing permissions and
*    limitations under the License.
*******************************************************************************/
package com.qinyeit.webapp.controller.management.materials;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.qinyeit.serviceapp.entity.*;
import com.qinyeit.serviceapp.entity.enums.*;
import com.qinyeit.serviceapp.exception.BusinessRunTimeException;
import com.qinyeit.serviceapp.service.branchs.BranchDataServiceImpl;
import com.qinyeit.serviceapp.service.branchstores.MaterialCostDetailService;
import com.qinyeit.serviceapp.service.dishes.DishesStoreService;
import com.qinyeit.serviceapp.service.dishes.DishesUnitService;
import com.qinyeit.serviceapp.service.materials.MaterialCategoryService;
import com.qinyeit.serviceapp.service.materials.MaterialService;
import com.qinyeit.serviceapp.service.materials.MaterialUnitService;
import com.qinyeit.serviceapp.service.materials.PurchaseSpecService;
import com.qinyeit.serviceapp.service.stores.StockService;
import com.qinyeit.webapp.controller.management.BaseManagementController;
import com.qinyeit.webapp.utils.CurrentAccountUtils;
import com.qinyeit.webapp.utils.SearchableUtils;
import com.qinyetech.springstage.core.date.DateUtils;
import com.qinyetech.springstage.core.entity.search.SearchFilterHelper;
import com.qinyetech.springstage.core.entity.search.SearchOperator;
import com.qinyetech.springstage.core.entity.search.Searchable;
import com.qinyetech.springstage.core.lang.QyMap;
import com.qinyetech.springstage.core.utils.JSONUtils;
import com.qinyetech.springstage.core.web.annotation.PageableDefaults;
import com.qinyetech.springstage.core.web.annotation.PermissionInfo;
import com.qinyetech.springstage.core.web.dto.ResponseResult;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * ClassName: MaterialsController <br/>
 * Function: material [物品管理] <br/>
 * date: 2018-11-07 11:42:52 <br/>
 *
 * @author liuwenjin
 * @version  1.0
 * @since JDK 1.8
 */
@RestController
@RequestMapping("/management/materials/materials")
@PermissionInfo(parentName ="基础信息管理" ,parentOrder = 10,order = 10,code = "management_material:read",name ="物品管理",deleteAble = false)
public class MaterialsController extends BaseManagementController{

	@Autowired
	private MaterialService materialService;
	@Autowired
    private MaterialCategoryService materialCategoryService;
	@Autowired
    private MaterialUnitService materialUnitService;
	@Autowired
    private PurchaseSpecService purchaseSpecService;
	@Autowired
    private MaterialCostDetailService materialCostDetailService;
	@Autowired
    private BranchDataServiceImpl branchDataService;
	@Autowired
    private StockService stockService;
	@Autowired
    private DishesUnitService dishesUnitService;
	@Autowired
    private DishesStoreService dishesStoreService;

    //TODO include的字段,支持jsonPath
	private final String [] keys = {"id","no","name","pinyin","spell","categoryId","goodsSpec","unit","minStock","maxStock","storeMode","purchaseNewPrice","consumeUnit","consumeRates","orderPriceBom","orderType","stocktakeType","state",
            "category","storeId","materialType"};

    @RequiresPermissions("management_material:show")
    @PermissionInfo(code = "management_material:show",name ="查看",deleteAble = false)
    @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})
    @PageableDefaults(sort = "id=desc")//默认按照id降序
    public ResponseResult<JSONObject> index(Searchable searchable,Long storeId){
        if(storeId==null){
            return fail("菜品库为空");
        }

        DishesStore dishesStore = dishesStoreService.findById(storeId);

        searchable = SearchableUtils.newSearchableWithMerchantFilter(searchable);
        //菜品库下的 或者 共享的
        searchable.addSearchFilter(SearchFilterHelper.or(
                SearchFilterHelper.newCondition("storeId",SearchOperator.eq,storeId),
                SearchFilterHelper.newCondition("storeId",SearchOperator.isNull,null)
        ));
//        searchable.addSearchParam("materialType_ne",MaterialType.PRODUCT);
        Page<Material> materialPage = materialService.findAll(searchable);

        QyMap map = QyMap.map("materials",JSONUtils.include(materialPage,
                new Class[]{State.class, OrderType.class, InventoryType.class, StoreMode.class,MaterialType.class}, keys));

        List<MaterialCategory> list=materialCategoryService.getBuildTree(CurrentAccountUtils.getAuthenticatedMerchantGroupID(),storeId);
        log.info("size = {}",list.size());
        MaterialCategory materialCategory=new MaterialCategory();
        materialCategory.setId(0L);
        materialCategory.setName("所有类别");
        materialCategory.setNo("0");
        list.add(0,materialCategory);
        map.setv("treeData",JSONUtils.include(list, "id","no","name","parentId","parentName","children"));

        map.setv("materialTypes",MaterialType.values());
        return ok("查询成功", map);
    }

    @GetMapping("/create")
    public ResponseResult<QyMap> _new(Long sid){
        QyMap map=QyMap.NEW();
        Material material = new Material();
        material.setNo(materialService.getNextNo("10001",CurrentAccountUtils.getAuthenticatedMerchantGroupID()));
        map.setv("material",JSONUtils.include(material, keys));
        initFormDate(map,sid);
        return ok("初始化成功", map);
    }

    @RequiresPermissions("management_material:create")
    @PermissionInfo(code = "management_material:create",name ="新增",deleteAble = false)
    @PostMapping("/create")
    public ResponseResult<String> create(@RequestBody JSONObject material, BindingResult bindingResult){

        if (bindingResult.hasErrors()) {
            return super.validateFail(bindingResult);
        }

        if(StringUtils.isBlank(material.getJSONObject("material").getString("no"))){
            return fail("请输入编号后保存");
        }
        if(materialService.exists(SearchableUtils.buildExists(material.getJSONObject("material").getLong("id"),"no",material.getJSONObject("material").getString("no")))){
            return fail("编号已经存在");
        }
        if(StringUtils.isBlank(material.getJSONObject("material").getString("name"))){
            return fail("请输入名称后保存");
        }
        if(materialService.exists(SearchableUtils.buildExists(material.getJSONObject("material").getLong("id"),"name",material.getJSONObject("material").getString("name")))){
            return fail("名称已经存在");
        }
        QyMap map = materialService.saveData(material,CurrentAccountUtils.getAuthenticatedMerchantGroupID());
        materialService.savePurchaseMaterial(map.getList("ids",Long.class),map.getLong("materialId"));
        return ok("保存成功");
    }

    @GetMapping("/{id}")
    public ResponseResult<JSONObject> show(@ModelAttribute Material material){
        return ok("查询成功", JSONUtils.include(material, keys));
    }

    @GetMapping("/{id}/update")
    public ResponseResult<QyMap> edit(@ModelAttribute Material material,Long sid){
        log.info("material : {}",JSON.toJSONString(material));
        QyMap map=QyMap.NEW();
        map.setv("material",JSONUtils.include(material, keys));

        Searchable searchable = SearchableUtils.newSearchableWithMerchantFilter();
        searchable.addSearchParam("material.id_eq",material.getId());
        List<PurchaseSpec> currents = purchaseSpecService.findWithSort(searchable);
        map.put("purchase", JSONUtils.include(currents, "id","name:purchaseSpec", "unit:purchaseUnit","ratio:purchaseCount", "price:purchasePrice"));
        initFormDate(map,sid);
        return ok("查询成功",map);
    }

    @RequiresPermissions("management_material:update")
    @PermissionInfo(code = "management_material:update",name ="修改",deleteAble = false)
    @PutMapping("/{id}/update")
    public ResponseResult<String> update(@RequestBody JSONObject material,BindingResult bindingResult){
        if (bindingResult.hasErrors()) {
            return super.validateFail(bindingResult);
        }

        if(StringUtils.isBlank(material.getJSONObject("material").getString("no"))){
            return fail("请输入编号后保存");
        }
        if(materialService.exists(SearchableUtils.buildExists(material.getJSONObject("material").getLong("id"),"no",material.getJSONObject("material").getString("no")))){
            return fail("编号已经存在");
        }
        if(StringUtils.isBlank(material.getJSONObject("material").getString("name"))){
            return fail("请输入名称后保存");
        }
        if(materialService.exists(SearchableUtils.buildExists(material.getJSONObject("material").getLong("id"),"name",material.getJSONObject("material").getString("name")))){
            return fail("名称已经存在");
        }
        QyMap map = materialService.saveData(material,CurrentAccountUtils.getAuthenticatedMerchantGroupID());

        materialService.savePurchaseMaterial(map.getList("ids",Long.class),map.getLong("materialId"));

        return ok("更新成功", null);
    }

    @RequiresPermissions("management_material:destory")
    @PermissionInfo(code = "management_material:destory",name ="删除",deleteAble = false)
    @DeleteMapping("/{id}")
    public ResponseResult<String> destory(@PathVariable Long id){

        Searchable searchable = SearchableUtils.newSearchableWithMerchantFilter();
        searchable.addSearchParam("materialId_eq",id);
        Long count = materialCostDetailService.count(searchable);
        if (count.intValue()>0){
            return fail("原料正在使用,不能删除");
        }
        //有库存
        searchable = SearchableUtils.newSearchableWithMerchantFilter();
        searchable.addSearchParam("materialId_eq",id);
        count = stockService.count(searchable);
        if (count.intValue()>0){
            return fail("原料有库存，不能删除");
        }

        Material material = materialService.findById(id);
        material.setUpdateTimestamp(DateUtils.current());
        materialService.update(material);
        materialService.logicDelete(id);
        return ok("删除成功", null);
    }

    /**
     * 获取物料信息 类别和物料列表 按物料类别和名称搜索
     * @param name  按照物品名称和编码进行检索
     * @return
     */
    @GetMapping("/getMaterialsByNameOrCode")
    public Object getMaterialsByNameOrCode(String name,Long storeId){
        if(storeId==null){
            return fail("请选择商品库");
        }
        QyMap map = QyMap.NEW();
        if(StringUtils.isNotBlank(name)){
            Searchable searchable=SearchableUtils.newSearchableWithMerchantFilter();
            //菜品库下的 或者 共享的
            searchable.addSearchFilter(SearchFilterHelper.or(
                    SearchFilterHelper.newCondition("material.storeId",SearchOperator.eq,storeId),
                    SearchFilterHelper.newCondition("material.storeId",SearchOperator.isNull,null)
            ));
            searchable.addSearchFilter("material.deleted", SearchOperator.eq, false);
            searchable.addSearchFilter(
                    SearchFilterHelper.or(
                            SearchFilterHelper.newCondition("material.name", SearchOperator.like,name),
                            SearchFilterHelper.newCondition("material.spell", SearchOperator.like,name),
                            SearchFilterHelper.newCondition("material.pinyin",SearchOperator.like,name),
                            SearchFilterHelper.newCondition("material.no",SearchOperator.like,name),
                            SearchFilterHelper.newCondition("material.code",SearchOperator.like,","+name)
                    )
            );

            searchable.setPage(0,15);
            Page<PurchaseSpec> materialPage= purchaseSpecService.findAll(searchable);
            List<PurchaseSpec> materialList = materialPage.getContent();
            List<QyMap> materials = Lists.newArrayList();
            QyMap item ;

            for(int i=0;i<materialList.size();i++){
                PurchaseSpec spec = materialList.get(i);
                Material material = spec.getMaterial();
                item = QyMap.NEW();
                item.setv("state", material.getState());
                item.setv("label", spec.getId());
                item.setv("materialId",material.getId());
                item.setv("no", material.getNo());
                item.setv("unit", material.getUnit());
                item.setv("nameValue", material.getName());
                item.setv("goodsSpec", material.getGoodsSpec());
                item.setv("purchaseSpec", spec.getName());
                item.setv("purchaseUnit", spec.getUnit());
                item.setv("purchasePrice", spec.getPrice());
                item.setv("purchaseNewPrice", spec.getHistoryPrice());
                item.setv("purchaseCount", spec.getRatio());
                item.setv("orderPriceBom", material.getOrderPriceBom());
                item.setv("value",material.getName());
                item.setv("codes",material.getCode());

                if(StringUtils.isNotBlank(material.getCode())){
                    //取一个编码
                    if(material.getCode().indexOf(","+name+",")!=-1){
                        item.setv("goodcode",name);
                    }else {
                        item.setv("goodcode",material.getCode().substring(1,material.getCode().indexOf(",",2)));
                    }
                    //将编码逗号分隔为数组
                   item.setv("goodcodes",StringUtils.split(material.getCode(),","));
                }else {
                    item.setv("goodcode","");
                    item.setv("goodcodes",null);
                }
                materials.add(item);
            }
            map.setv("materialList", materials);
        }
        return ok("查询成功", map);
    }


    /**
     * 获取物料信息 类别和物料列表  按物料类别和名称搜索
     * @param searchable
     * @return
     */
    @GetMapping("/getMaterials")
    public Object getMaterials(Searchable searchable,Long storeId){
        if (storeId==null){
            return fail("商品库为空");
        }
        QyMap map = QyMap.NEW();
        //物料类别
        List<MaterialCategory> list=materialCategoryService.getBuildTree(CurrentAccountUtils.getAuthenticatedMerchantGroupID(),storeId);
        MaterialCategory category = new MaterialCategory();
        category.setNo("0");
        category.setName("所有类别");
        category.setId(0L);
        list.add(0,category);
        map.setv("treeData",list);

        //物料列表
        if(StringUtils.isNotBlank(searchable.getValue("category.id_eq"))){
            String cate=searchable.getValue("category.id_eq").toString();
            searchable.removeSearchFilter("category.id_eq");
            if(!"0".equals(cate)){
                searchable.addSearchFilter(SearchFilterHelper.or(
                        SearchFilterHelper.newCondition("material.category.parentIds_like", "/"+cate+"/"),
                        SearchFilterHelper.newCondition("material.category.id_eq", cate)
                ));
            }
        }

        if(StringUtils.isNotBlank(searchable.getValue("code_eq"))){
            String code=searchable.getValue("code_eq").toString();
            searchable.removeSearchFilter("code_eq");
            searchable.addSearchFilter(SearchFilterHelper.or(
                    SearchFilterHelper.newCondition("material.no_like", code),
                    SearchFilterHelper.newCondition("material.name_like", code)
            ));
        }
        searchable.addSearchFilter("material.deleted", SearchOperator.eq, false);
        //菜品库下的 或者 共享的
        searchable.addSearchFilter(SearchFilterHelper.or(
                SearchFilterHelper.newCondition("material.storeId",SearchOperator.eq,storeId),
                SearchFilterHelper.newCondition("material.storeId",SearchOperator.isNull,null)
        ));
        searchable = SearchableUtils.newSearchableWithMerchantFilter(searchable);

        log.info(">>>>>> searchable : {} ",JSON.toJSONString(searchable));

        Page<PurchaseSpec> materialList = purchaseSpecService.findAll(searchable);
        map.setv("materialList",JSONUtils.include(materialList,new Class[]{State.class},
                "id",
                "material.id:materialId",
                "material.no:no",
                "material.name:name",
                "material.goodsSpec:goodsSpec",
                "name:purchaseSpec",
                "unit:purchaseUnit",
                "material.unit:unit",
                "price:purchasePrice",
                "historyPrice:purchaseNewPrice",
                "ratio:purchaseCount",
                "material.consumeUnit:consumeUnit",
                "material.orderPriceBom:orderPriceBom",
                "material.state:state",
                "material.code:codes"
                )
        );
        return ok("查询成功", map);
    }

    /**
     * 获取物料信息 类别和物料列表  按物料类别和名称搜索
     * @param searchable
     *      name_eq
     *      categoryId_eq
     * @return
     */
    @GetMapping("/getMaterialsForBranch")
    public Object getMaterialsForBranch(Searchable searchable){
        QyMap map = QyMap.NEW();
        //获取单店的物料信息
        Page<Map<String,Object>> materialPage = branchDataService.getPurchaseMaterials(searchable);
        map.setv("materialPage",materialPage);
        //获取单店的物料类别
        String branchId = searchable.getValue("branchId_eq");
        if (com.qinyetech.springstage.core.lang.StringUtils.isBlank(branchId)){
            throw new BusinessRunTimeException("请选择门店",10001);
        }
        List<Map<String,Object>> categorys = branchDataService.getMaterialCategorys(branchId);
        Map<String,Object> item = Maps.newHashMap();
        item.put("no","0");
        item.put("name","所有类别");
        item.put("id",0L);
        categorys.add(0,item);
        map.setv("treeData",categorys);
        return ok("查询成功", map);
    }


    /**
     * 获取商品列表 出库  //调拨 没有商品库
     * @param warehouseId
     * @param keywords
     * @param categoryId
     * @param inventoryType 盘点类型
     * @return
     */
    @GetMapping("/getMaterialsByNameOrCodeForOut")
    public Object getMaterialsForOut(Searchable searchable,Long warehouseId,String keywords,Long categoryId,String inventoryType,Boolean pandian,Long storeId){
       /* if (storeId==null){
            return fail("请选择商品库");
        }*/
        QyMap map = QyMap.NEW();
        //物料类别
        List<MaterialCategory> list=materialCategoryService.getBuildTree(CurrentAccountUtils.getAuthenticatedMerchantGroupID(),storeId);
        MaterialCategory category = new MaterialCategory();
        category.setNo("0");
        category.setName("所有类别");
        category.setId(0L);
        list.add(0,category);
        map.setv("treeData",list);
        Page<Map<String,Object>> mapList = materialService.getMaterialsForOut(CurrentAccountUtils.getAuthenticatedMerchantGroupID(),searchable,warehouseId,keywords,categoryId,inventoryType,pandian,storeId);

        map.put("materials",mapList);
        return ok("查询成功", map);
    }



    /**
     * 获取商品列表 盘点
     * @param warehouseId
     * @param keywords
     * @param categoryId
     * @param inventoryType 盘点类型
     * @return
     */
    @GetMapping("/getMaterialsForPandian")
    public Object getMaterialsForPandian(Searchable searchable,Long warehouseId,String keywords,Long categoryId,String inventoryType,Boolean pandian,Long storeId){
        QyMap map = QyMap.NEW();
        //物料类别
        List<MaterialCategory> list=materialCategoryService.getBuildTree(CurrentAccountUtils.getAuthenticatedMerchantGroupID(),storeId);
        map.setv("treeData",list);
        List<Map<String,Object>> mapList = materialService.getMaterialsForPandian(searchable,CurrentAccountUtils.getAuthenticatedMerchantGroupID(),warehouseId,keywords,categoryId,inventoryType,pandian,storeId);
        map.put("materials",mapList);
        return ok("查询成功", map);
    }

    /**
     * 获取菜品库下的菜品分类和菜品
     *
     * @param storeId
     * @return
     */
    @GetMapping("/getMaterialByStoreId")
    public ResponseResult<String> getDishes(Long storeId){
        if (storeId==null){
            return fail("请选择菜品库",10001);
        }
        List<MaterialCategory> categoryList = materialService.getMaterialByStoreId(storeId,CurrentAccountUtils.getAuthenticatedMerchantGroupID());
        return ok("查询成功", categoryList);
    }


    @ModelAttribute
    public void preparedData(@PathVariable(value="id",required = false) String id,Model model){
        log.info("------------------id:{}",id);
        if(StringUtils.isNotBlank(id)){ //如果路径中有id参数则查询实体对象
            Material material = materialService.findById(Long.valueOf(id));
            model.addAttribute(material);
        }
    }

    /**
     * 初始化表单数据
     * @param qyMap
     */
    private void initFormDate(QyMap qyMap,Long storeId){
        List<MaterialCategory> list=materialCategoryService.getBuildTree(CurrentAccountUtils.getAuthenticatedMerchantGroupID(),storeId,true);
        qyMap.setv("treeData",list);
        Searchable searchable= SearchableUtils.newSearchableWithMerchantFilter();
        searchable.addSearchParam("storeId_eq",storeId);
        qyMap.setv("units", JSONUtils.include(dishesUnitService.findWithSort(searchable),"id","name","state"));

        qyMap.setv("states", State.values())
                .setv("stocktakeTypes", InventoryType.values())
                .setv("orderTypes", OrderType.values())
                .setv("storeMode", StoreMode.values())
        .setv("materialTypes", MaterialType.values());
    }

}